package de.szut.sudoku.cui;

import java.util.ArrayList;

import de.szut.sudoku.game.field.FieldGroup;
import de.szut.sudoku.game.field.SudokuField;

/**
 * Class for generating a visual field
 * 
 * @author dqi12huisinga
 * 
 */
public class VisualFieldGenerator {
	private Character[][] visualField;
	private int[] positions;
	private ArrayList<Integer[]> presetBoxes;

	public ArrayList<Integer[]> getPresetBoxes() {
		return presetBoxes;
	}

	public void setPresetBoxes(ArrayList<Integer[]> presetBoxes) {
		this.presetBoxes = presetBoxes;
	}

	public Character[][] getVisualField() {
		return visualField;
	}

	public void setVisualField(Character[][] visualField) {
		this.visualField = visualField;
	}

	/**
	 * Generates the visual field on the basis of a sudokufield
	 * 
	 * @param field
	 */
	public void generateVisualFieldFromField(SudokuField field) {
		int yIndex = 0;
		// iterates through the entire field 2dimensionally on a horizontal
		// basis
		for (FieldGroup currentRow : field.getHorizontalGroups()) {
			int xIndex = 0;
			for (int currentRowElem : currentRow.getStates()) {
				// sets the field position to an empty value if the value is 0
				if (currentRowElem == 0) {
					visualField[positions[yIndex]][positions[xIndex]] = ' ';
				} else {
					// enters the preset position and adds the position to
					// blocked positions so the user can't select this value
					visualField[positions[yIndex]][positions[xIndex]] = Integer
							.toString(currentRowElem).toCharArray()[0];
					Integer[] blockedPosition = { xIndex, yIndex };
					presetBoxes.add(blockedPosition);
				}

				xIndex++;
			}
			yIndex++;
		}
	}

	/**
	 * Generates the borders of the field
	 */
	private void generateBorders() {
		// 2d field
		Character[][] borderField = {
				{ ' ', ' ', '1', '2', '3', ' ', '4', '5', '6', ' ', '7', '8',
						'9', ' ' },
				{ ' ', '╔', '═', '═', '═', '╦', '═', '═', '═', '╦', '═', '═',
						'═', '╗' },
				{ '1', '║', ' ', ' ', ' ', '║', ' ', ' ', ' ', '║', ' ', ' ',
						' ', '║' },
				{ '2', '║', ' ', ' ', ' ', '║', ' ', ' ', ' ', '║', ' ', ' ',
						' ', '║' },
				{ '3', '║', ' ', ' ', ' ', '║', ' ', ' ', ' ', '║', ' ', ' ',
						' ', '║' },
				{ ' ', '╠', '═', '═', '═', '╬', '═', '═', '═', '╬', '═', '═',
						'═', '╣' },
				{ '4', '║', ' ', ' ', ' ', '║', ' ', ' ', ' ', '║', ' ', ' ',
						' ', '║' },
				{ '5', '║', ' ', ' ', ' ', '║', ' ', ' ', ' ', '║', ' ', ' ',
						' ', '║' },
				{ '6', '║', ' ', ' ', ' ', '║', ' ', ' ', ' ', '║', ' ', ' ',
						' ', '║' },
				{ ' ', '╠', '═', '═', '═', '╬', '═', '═', '═', '╬', '═', '═',
						'═', '╣' },
				{ '7', '║', ' ', ' ', ' ', '║', ' ', ' ', ' ', '║', ' ', ' ',
						' ', '║' },
				{ '8', '║', ' ', ' ', ' ', '║', ' ', ' ', ' ', '║', ' ', ' ',
						' ', '║' },
				{ '9', '║', ' ', ' ', ' ', '║', ' ', ' ', ' ', '║', ' ', ' ',
						' ', '║' },
				{ ' ', '╚', '═', '═', '═', '╩', '═', '═', '═', '╩', '═', '═',
						'═', '╝' } };
		visualField = borderField;
	}

	/**
	 * Prepares the values on the field
	 */
	private void generateValues() {
		// iterates through the field and sets all the values to an empty value
		for (int xIndex = 0; xIndex < 9; xIndex++) {
			for (int yIndex = 0; yIndex < 9; yIndex++) {
				visualField[positions[yIndex]][positions[xIndex]] = ' ';
			}
		}
	}

	public VisualFieldGenerator() {
		visualField = new Character[14][14];
		presetBoxes = new ArrayList<Integer[]>();
		// real visual field positions
		// index: 2d normal position (1-9)
		// value: real field position
		int[] positions = { 2, 3, 4, 6, 7, 8, 10, 11, 12 };
		this.positions = positions;
		// generates the borders and prepares the values
		generateBorders();
		// is unnecessary, was originally planned for the implementation of save
		// and load for the cui
		generateValues();
	}

	/**
	 * Prints the visual field
	 */
	public void printVisualField() {
		for (Character[] currentLine : visualField) {
			for (Character currentChar : currentLine) {
				System.out.print(currentChar);
			}
			System.out.println();
		}
	}

	/**
	 * Checks if the preset boxes contain a certain position
	 * 
	 * @param xPosition
	 * @param yPosition
	 * @return
	 */
	private boolean presetBoxesDeepContains(int xPosition, int yPosition) {
		for (Integer[] currentElem : presetBoxes) {
			if (currentElem[0] == xPosition && currentElem[1] == yPosition) {
				return true;
			}
		}
		return false;
	}

	/**
	 * Updates the value on the field
	 * 
	 * @param value
	 * @param xPosition
	 * @param yPosition
	 */
	public void updateValue(int value, int xPosition, int yPosition) {
		// sets the value to ' ' if the value is 0
		if (value == 0) {
			visualField[positions[yPosition]][positions[xPosition]] = ' ';
		} else {
			// checks if the position is preset and updates the value on the
			// field should this not be the case
			if (!presetBoxesDeepContains(xPosition, yPosition)) {
				visualField[positions[yPosition]][positions[xPosition]] = Integer
						.toString(value).toCharArray()[0];
			}
		}

	}

	public int[] getPositions() {
		return positions;
	}

	public void setPositions(int[] positions) {
		this.positions = positions;
	}

}
